#pragma once

#include <maths.h>
#include "src\mesh.h"
#include "src\material.h"

class model
{
public:
	model();
	~model();

	void clear();

	void set_name(const std::string &name);
	void set_meshes(const mesh_vec &meshes);
	void set_materials(const material_vec &materials);
	void set_transforms(const matrix4 &pos);
	void set_node_animation(animation_ptr anm);
	void set_skeletal_animation(skeleton_ptr skl);

	void add_mesh(const mesh_ptr &m);
	void add_material(const material_ptr &m);
	void add_child(const model_ptr &m);

	std::string get_name() const;
	const matrix4 &get_transforms() const;

	material_ptr get_material(size_t id) const;
	mesh_ptr get_mesh(size_t id) const;
	model_ptr get_child(size_t id) const;
	animation_ptr get_node_animation() const;
	skeleton_ptr get_skeletal_animation() const;

	const material_vec &get_materials() const;
	const mesh_vec &get_meshes() const;
	const model_vec &get_childs() const;

	size_t get_num_meshes() const;
	size_t get_num_materials() const;
	size_t get_num_childrens() const;

	bool is_empty() const;

private:
	mesh_vec			m_meshes;
	material_vec		m_materials;
	model_vec			m_childrens;

	std::string			m_name;

	matrix4				m_tm;

	animation_ptr	m_node_animation;
	skeleton_ptr	m_skeleton;
};

inline model::model() { }

inline model::~model() { }

inline void model::set_name(const std::string &name) { m_name = name; }

inline void model::set_meshes(const mesh_vec &meshes) { m_meshes = meshes; }

inline void model::set_materials(const material_vec &materials) { m_materials = materials; }

inline void model::set_transforms(const matrix4 &tm) { m_tm = tm; }

inline void model::set_node_animation(animation_ptr anm) { m_node_animation = anm; }

inline void model::set_skeletal_animation(skeleton_ptr skl) { m_skeleton = skl; }

inline void model::add_mesh(const mesh_ptr &m) { m_meshes.push_back(m); }

inline void model::add_material(const material_ptr &m) { m_materials.push_back(m); }

inline void model::add_child(const model_ptr &m) { m_childrens.push_back(m); }

inline std::string model::get_name() const { return m_name; }

inline mesh_ptr model::get_mesh(size_t id) const { return m_meshes[id]; }

inline material_ptr model::get_material(size_t id) const { return m_materials[id]; }

inline model_ptr model::get_child(size_t id) const { return m_childrens[id]; }

inline const material_vec &model::get_materials() const { return m_materials; }

inline const mesh_vec &model::get_meshes() const { return m_meshes; }

inline const model_vec &model::get_childs() const { return m_childrens; }

inline const matrix4 &model::get_transforms() const { return m_tm; }

inline size_t model::get_num_meshes() const { return m_meshes.size(); }

inline size_t model::get_num_materials() const { return m_materials.size(); }

inline size_t model::get_num_childrens() const { return m_childrens.size(); }

inline animation_ptr model::get_node_animation() const { return m_node_animation; }

inline skeleton_ptr model::get_skeletal_animation() const { return m_skeleton; }

inline void model::clear()
{
	m_meshes.clear();
	m_materials.clear();
	m_childrens.clear();
	m_name.clear();
	m_node_animation.release();
	m_tm = matrix4();
}

inline bool model::is_empty() const
{
	if(get_num_meshes() > 0)
		return false;
	for(size_t i = 0; i < get_num_childrens(); i++) {
		if(!get_child(i)->is_empty())
			return false;
	}
	return true;
}